﻿using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using WJP.Dependency;
using WJP.Events.Bus.Handlers;
using System.Reflection;
using WJP.Events.Bus.Factories;

namespace WJP.Events.Bus
{
    /// <summary>
    /// 安装事件总线系统并自动注册所有事件处理器。
    /// </summary>
    public class EventBusInstaller : IWindsorInstaller
    {
        private readonly IIocResolver _iocResolver;
        private IEventBus _eventBus;

        public EventBusInstaller()
        {

        }

        public EventBusInstaller(IIocResolver iocResolver)
        {
            _iocResolver = iocResolver;
        }

        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<IEventBus>().UsingFactoryMethod(() =>
                  EventBus.Default).LifestyleSingleton()
                );

            _eventBus = container.Resolve<IEventBus>();

            container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
        }

        /// <summary>
        /// 当一个新组件注册时触发事件。
        /// <para>这段代码检查注册组件是否实现了IEventHandler&lt;TEventData&gt;接口</para>
        /// <para>如果实现了，则获取所有事件处理器接口，并为每个处理事件登记类型到事件总线。</para>
        /// </summary>
        /// <param name="key">识别组件的键</param>
        /// <param name="handler">持有该组件的处理器，并且能够创建它的实例</param>
        private void Kernel_ComponentRegistered(string key, IHandler handler)
        {
            if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(handler.ComponentModel.Implementation))
            {
                return;
            }

            var interfaces = handler.ComponentModel.Implementation.GetTypeInfo().GetInterfaces();
            foreach (var @interface in interfaces)
            {
                if (!typeof(IEventHandler).GetTypeInfo().IsAssignableFrom(@interface))
                    continue;

                var genericArgs = @interface.GetGenericArguments();
                if (genericArgs.Length == 1)
                {
                    _eventBus.Register(genericArgs[0], new IocHandlerFactory(_iocResolver, handler.ComponentModel.Implementation));
                }
            }
        }
    }
}
